package main

import (
	"fmt"
	"net"
	"os"
	"strings"
	"time"
	"os/signal"
	"syscall"
	"log"
	"regexp"

	"google.golang.org/grpc"
	_ "./config" // 加载配置文件
	pb "./protobuf"
	c "./controller"
	grpclb "./etcdv3"
)

func main() {
	// 初始化服务配置
	initServerConfig()
	// 初始化服务
	server := initServer()
	// 注册服务
	registerPbServer(server)
	// 负载平衡
	loadBalancer()
	// 启动服务
	runServer(server)
}

// 初始化服务配置
var (
	localIp          string                   // 本地ip
	serverNamePrefix string                   // 服务名
	serverName       string                   // 服务名
	serverIp         string                   // 服务ip
	serverPort       string                   // 服务端口
	etcdHostString   string                   // etcd服务地址
	etcdTtl          int64 = 15               // etcdTtl=15s
	keepAliveEtcdTtl       = 10 * time.Second // 每10秒续期etcdTtl
)

// initServerConfig
func initServerConfig() {
	serverNamePrefix = getEnv("ServerNamePrefix")
	serverName = getEnv("ServerName")
	serverIp = getEnv("ServerIp")
	serverPort = getEnv("ServerPort")
	etcdHostString = getEnv("EtcdHost")
	initLocalIp()   // 出生本地地址
	checkServerIp() // 服务地址是否合法
}

// 负载平衡
func loadBalancer() {
	// etcdHost
	etcdHost := strings.Split(etcdHostString, ",")
	// keep alive
	if time.Duration(etcdTtl)*time.Second <= keepAliveEtcdTtl {
		panic("keepAliveEtcdTtl value must less than etcdTtl")
	}
	// register
	if err := grpclb.Register(serverNamePrefix, serverName, serverIp, serverPort, etcdHost, etcdTtl, keepAliveEtcdTtl); err != nil {
		panic(err)
	}
	// unRegister
	osSignalChan := make(chan os.Signal, 1)
	signal.Notify(osSignalChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL, syscall.SIGHUP, syscall.SIGQUIT)
	go func() {
		s := <-osSignalChan
		log.Printf("receive signal '%v'", s)
		grpclb.UnRegister()
		os.Exit(1)
	}()
}

// register pb Server
func registerPbServer(s *grpc.Server) {
	pb.RegisterKgTestServer(s, &c.Test{})
}

// run Server
func runServer(s *grpc.Server) {
	ipPort := ":" + serverPort
	// listen serverAddress
	listener, err := net.Listen("tcp", ipPort)
	if err != nil {
		panic(err)
	}
	fmt.Println("server address : ", ipPort)
	// run server
	if err := s.Serve(listener); err != nil {
		panic(err)
	}
}

// initServer
func initServer() *grpc.Server {
	return grpc.NewServer()
}

// getEnv
func getEnv(key string) (value string) {
	value = os.Getenv(key)
	if value == "" {
		fmt.Println(key, " value is empty or not exist")
	}
	return value
}

// 初始化
func initLocalIp() {
	network, address := "tcp", "163.com:80"
	conn, err := net.Dial(network, address)
	if err != nil {
		fmt.Printf("net.Dial(%v, %v) error : %v \n", network, address, err)
	}
	defer conn.Close()
	localIp = strings.Split(conn.LocalAddr().String(), ":")[0]
}

// checkServerIp
func checkServerIp() {
	ipReg := `^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$`
	// 服务地址不合法
	if !regexp.MustCompile(ipReg).MatchString(serverIp) {
		serverIp = localIp
	}
}
